package com.d.lib.ui.view.tick;

import com.d.lib.ui.view.AnimatorValueUtils;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.render.PathMeasure;
import ohos.agp.utils.Color;
import ohos.app.Context;

public class STickView extends Component implements Component.DrawTask,
    Component.EstimateSizeListener {
  private final long DURATION = 600; // Anim duration

  private int mWidth;
  private int mHeight;

  private float mFactor;
  private float mScaleAX = 0.2659f;
  private float mScaleAY = 0.4588f;
  private float mScaleBX = 0.4541f;
  private float mScaleBY = 0.6306f;
  private float mScaleCX = 0.7553f;
  private float mScaleCY = 0.3388f;

  private static final int WHITE_COLOR = 0xFFFFFFFF;
  private static final int REST_COLOR = 0xFF47b018;

  private Color mColor;
  private Color mColorCircle;
  private float mStrokeWidth;
  private Path mPath;
  private Path mPathTick;
  private Paint mPaintTick;
  private Paint mPaintCircle;
  private PathMeasure mTickPathMeasure;
  private AnimatorValue mAnimation;

  public STickView(Context context) {
    this(context, null);
  }

  public STickView(Context context, AttrSet attrs) {
    this(context, attrs, 0);
  }

  public STickView(Context context, AttrSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mColor = attrs.getAttr("CTickView_lib_ui_view_ctv_color").isPresent() ?
        attrs.getAttr("CTickView_lib_ui_view_ctv_color").get().getColorValue() :
        new Color(WHITE_COLOR);
    mColorCircle = attrs.getAttr("CTickView_lib_ui_view_ctv_colorCircle").isPresent() ?
        attrs.getAttr("CTickView_lib_ui_view_ctv_colorCircle").get().getColorValue() :
        new Color(REST_COLOR);
    mStrokeWidth = attrs.getAttr("CTickView_lib_ui_view_ctv_strokeWidth").isPresent() ?
        attrs.getAttr("CTickView_lib_ui_view_ctv_strokeWidth").get().getDimensionValue() :
        AttrHelper.vp2px(3.5f, context);
    init();
  }

  public void init() {
    setEstimateSizeListener(this);
    addDrawTask(this);

    mPath = new Path();
    mPathTick = new Path();

    mTickPathMeasure = new PathMeasure(null, false);

    mPaintCircle = new Paint();
    mPaintCircle.setColor(mColorCircle);

    mPaintTick = new Paint();
    mPaintTick.setColor(mColor);
    mPaintTick.setStyle(Paint.Style.STROKE_STYLE);
    mPaintTick.setStrokeWidth(mStrokeWidth);

    mAnimation = new AnimatorValue();
    mAnimation.setDuration(DURATION);
//        mAnimation.setInterpolator(new SpringScaleInterpolator(0.4f));
    mAnimation.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
      @Override
      public void onUpdate(AnimatorValue animation, float v) {
        if (mPaintCircle != null && mPaintTick != null) {
          float alpha = 1f * animation.getDuration() / DURATION;
          alpha = Math.min(alpha, 1f);
          alpha = Math.max(alpha, 0f);
          mPaintCircle.setAlpha((int) (1f * alpha));
          mPaintTick.setAlpha((int) (1f * alpha));
        }
        mFactor = AnimatorValueUtils.getAnimatedValue(v, 0f, 0.5f, 0.8f, 1f, 0.8f);
//                mFactor = mFactor / 1.27f;
        mFactor = Math.min(mFactor, 1f);
        mFactor = Math.max(mFactor, 0f);
        invalidate();
      }
    });

  }

  @Override
  public void onDraw(Component component, Canvas canvas) {
    float width = this.mWidth * 0.85f * mFactor;
    float height = this.mHeight * 0.85f * mFactor;
    float startX = (this.mWidth - width) / 2f;
    float startY = (this.mHeight - height) / 2f;
    mPath.reset();
    mPathTick.reset();
    mPathTick.moveTo(startX + width * mScaleAX, startY + height * mScaleAY);
    mPathTick.lineTo(startX + width * mScaleBX, startY + height * mScaleBY);
    mPathTick.lineTo(startX + width * mScaleCX, startY + height * mScaleCY);
    mTickPathMeasure.setPath(mPathTick, false);
    /*
     * On KITKAT and earlier releases, the resulting path may not display on a
     * hardware-accelerated Canvas.
     * A simple workaround is to add a single operation to this path, such as dst.rLineTo(0, 0).
     */
    mTickPathMeasure.getSegment(0, mTickPathMeasure.getLength(), mPath, true);
    width = this.mWidth * mFactor;
    height = this.mHeight * mFactor;
    startX = (this.mWidth - width) / 2f;
    startY = (this.mHeight - height) / 2f;
    canvas.drawCircle(startX + width / 2f, startY + width / 2f, width / 2f, mPaintCircle);
    mPaintTick.setStrokeWidth(mStrokeWidth * mFactor);
    canvas.drawPath(mPath, mPaintTick);
  }

  @Override
  public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
    mWidth = MeasureSpec.getSize(widthMeasureSpec);
    mHeight = MeasureSpec.getSize(heightMeasureSpec);
    setEstimatedSize(mWidth, mHeight);
    return false;
  }

  /**
   * Start animation
   */
  public void start() {
    stop();
    mPath = new Path();
    if (mAnimation != null) {
      mAnimation.start();
    }
  }

  /**
   * Stop animation
   */
  public void stop() {
    if (mAnimation != null) {
      mAnimation.end();
    }
  }

//    class SpringScaleInterpolator implements Interpolator {
//        private float factor;
//
//        SpringScaleInterpolator(float factor) {
//            this.factor = factor;
//        }
//
//        @Override
//        public float getInterpolation(float input) {
//            return (float) (Math.pow(2, -10 * input) * Math.sin((input - factor / 4) * (2 *
//            Math.PI) / factor) + 1);
//        }
//    }
}
